home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 73747 / 73747.xpi / texto.jar / content / pref-texto.js < prev    next >
Text File  |  2010-02-08  |  15KB  |  430 lines

  1. /*
  2. The contents of this file are subject to the Mozilla Public
  3. License Version 1.1 (the "License"); you may not use this file
  4. except in compliance with the License. You may obtain a copy of
  5. the License at http://www.mozilla.org/MPL/
  6.  
  7. Software distributed under the License is distributed on an "AS
  8. IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9. implied. See the License for the specific language governing
  10. rights and limitations under the License.
  11.  
  12. Alternatively, the contents of this file may be used under the
  13. terms of the GNU General Public License Version 2 or later (the
  14. "GPL"), in which case the provisions of the GPL are applicable 
  15. instead of those above.
  16.  
  17. Copyright (C) 2002 Tomas Styblo <tripie@cpan.org>
  18. */
  19.  
  20. var texto_prefs = Components.classes["@mozilla.org/preferences-service;1"].
  21.     getService(Components.interfaces.nsIPrefService).getBranch("texto.");
  22. var dbConn = null;
  23. var texto_domain_prefs = null;
  24. var GLOBAL_QUERY_STATUS_THINGY = 0;
  25.  
  26. /* DEBUG */
  27. var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
  28.                                    .getService(Components.interfaces.nsIConsoleService);
  29. /* END DEBUG */
  30.  
  31. function textoReadPref(name) {
  32.     if(name.indexOf('texto.') == 0){
  33.         name = name.substring('texto.'.length);
  34.     }
  35.  
  36.     if (texto_prefs.prefHasUserValue(name)) {
  37.         var type = texto_prefs.getPrefType(name);
  38.         if (type & 128) {
  39.             return texto_prefs.getBoolPref(name);
  40.         }
  41.         else if (type & 64) {
  42.             return texto_prefs.getIntPref(name);
  43.         }
  44.         else if (type & 32) {
  45.             return texto_prefs.getCharPref(name);
  46.         }
  47.         else {
  48.             return null;
  49.         }
  50.     }
  51.     else {
  52.         return null;
  53.     }
  54. }
  55.  
  56. function initMozexPrefPanel(defaults) {
  57.     var nodes = defaults.querySelectorAll('textbox');
  58.     for(var i=0; i<nodes.length; i++){
  59.         var node = nodes.item(i);
  60.         node.value = textoReadPref(node.id);
  61.         node.addEventListener("blur", function(e){  updateMozexPref(e.target); return true; }, true);
  62.     }
  63.     // handle the little checkbox:
  64.     var gd = document.getElementById("texto.default.enabled");
  65.     gd.checked = textoReadPref(gd.id);
  66.     gd.addEventListener("command",
  67.             function(e){ texto_prefs.setBoolPref("default.enabled", gd.checked); return true; },
  68.             true);
  69.  
  70.     // handler for add button:
  71.     var addButt = document.getElementById("texto.domain.add");
  72.     var domainField = document.getElementById("texto.domain.new");
  73.     addButt.addEventListener("command",
  74.             function(e){
  75.                 var obj = { 'textoOptEnabled' : true };
  76.                 addExtensionPrefObj(domainField.value, 'texto', obj, function(){ insertNewDomain(domainField.value, JSON.stringify(obj), true); domainField.value = 'New Domain'; }); return true; },
  77.             true);
  78.     domainField.addEventListener("focus", function(e){ domainField.value = ""; return true; }, true);
  79.  
  80.     // delete button:
  81.     var delButt = document.getElementById("textoOptDelete");
  82.     delButt.addEventListener("command",
  83.             function(e){
  84.                 delDomainPref(document.getElementById("textoOptDomain").value, 'texto', function(){ var n = document.getElementById("texto.domain.list"); n.removeChild(n.childNodes[n.selectedIndex]); resetDomainPrefDialog(); });
  85.                 return true; },
  86.             true);
  87.     // save button:
  88.     var saveButt = document.getElementById("textoOptSave");
  89.     saveButt.addEventListener("command",
  90.             function(e){
  91.                 // what we are gonna do here is save this thing
  92.                 // get the "domain" value
  93.                 var domain = document.getElementById("textoOptDomain").value;
  94.                 // build the json object
  95.                 var jsonObj = {};
  96.                 var opts = {"textoOptEditor":'value', "textoOptArgs":'value', "textoOptAuto":'value', "textoOptEnabled":'checked'};
  97.                 for(var o in opts){ jsonObj[o] = document.getElementById(o)[opts[o]]; }
  98.                 var jsonStr = JSON.stringify(jsonObj);
  99.                 // save it all
  100.                 addDomainPrefStr(
  101.                     domain,
  102.                     'texto',
  103.                     jsonStr,
  104.                     function(){
  105.                         var list = document.getElementById('texto.domain.list');
  106.                         list.childNodes[list.selectedIndex].value = jsonStr;
  107.                         });
  108.                 return true;
  109.             },
  110.             true);
  111.  
  112.     // browse for app dialog
  113.     var appButt = document.getElementById("texto.default.editorbrowse");
  114.     appButt.addEventListener(
  115.             'command',
  116.             function(e){ textoAppPicker(e, document.getElementById('texto.default.editor')); return true; },
  117.             true);
  118.     var domainButt = document.getElementById("texto.domain.editorbrowse");
  119.     domainButt.addEventListener(
  120.             'command', 
  121.             function(e){ textoAppPicker(e, document.getElementById('textoOptEditor')); return true; },
  122.             true);
  123.     initDomainListing();
  124.     resetDomainPrefDialog();
  125. }
  126. function textoAppPicker(e, field){
  127.     var nsIFilePicker = Components.interfaces.nsIFilePicker;
  128.     var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
  129.     fp.init(window, "Select a File", nsIFilePicker.modeOpen);
  130.     var plat = window.navigator.platform.toLowerCase();
  131.     var localDir = null;
  132.     if(plat.indexOf("mac") != -1){
  133.         //localDir.initWithPath("LocApp");
  134.         localDir = Components.classes["@mozilla.org/file/directory_service;1"].
  135.             getService(Components.interfaces.nsIProperties).
  136.             get("LocApp", Components.interfaces.nsIFile);
  137.  
  138.     } else if(plat.indexOf("win") != -1){
  139.         //localDir.initWIthPath("ProgF");
  140.         localDir = Components.classes["@mozilla.org/file/directory_service;1"].
  141.             getService(Components.interfaces.nsIProperties).
  142.             get("ProgF", Components.interfaces.nsIFile);
  143.  
  144.     }
  145.     if(localDir){ fp.displayDirectory = localDir; }
  146.     fp.appendFilters(nsIFilePicker.filterApps);
  147.  
  148.     var result = fp.show();
  149.     if(result == nsIFilePicker.returnOK) {
  150.         field.value = fp.file.path;
  151.         // focus because we use blur event to save changes:
  152.         field.focus();
  153.     }
  154. }
  155.  
  156. function insertNewDomain(domain, value, andScroll){
  157.     var listbox = document.getElementById("texto.domain.list");
  158.     var indent = "";
  159.     var rdomain = urlReverse(domain);
  160.     for(var i = 0; i < listbox.childNodes.length; i++){
  161.         if(typeof(listbox.childNodes[i].label) == "undefined"){
  162.             continue;
  163.         }
  164.         if(isSubdomain(listbox.childNodes[i].label, domain)){
  165.             indent += "  ";
  166.         }
  167.         if(domainCmp(domain,listbox.childNodes[i].label) == -1){
  168.             // insert domain at index 'i'
  169.             break;
  170.         }
  171.     }
  172.     var newitem = listbox.insertItemAt(i, indent + domain, value);
  173.     if(typeof(andScroll) != 'undefined'){
  174.         listbox.ensureElementIsVisible(newitem);
  175.         listbox.selectItem(newitem);
  176.     }
  177.     return;
  178. }
  179.  
  180. function initDomainListing(focusEl){
  181.     var lb = document.getElementById('texto.domain.list');
  182.     if(lb == null){ return; }
  183.     getExtensionPrefList('texto',
  184.         function(prefList){
  185.             texto_domain_prefs = prefList;
  186.             while(lb.hasChildNodes()){
  187.                 lb.removeChild(lb.firstChild);
  188.             }
  189.             for(var p in prefList){
  190.                 insertNewDomain(urlReverse(p), prefList[p]);
  191.             }
  192.             if(focusEl){
  193.                 item = lb.querySelector("listitem[value='" + focusEl + "']");
  194.                 if(item){
  195.                     lb.ensureElementIsVisible(item);
  196.                     lb.selectItem(item);
  197.                 }
  198.             }
  199.         }
  200.     );
  201.     lb.addEventListener("select",
  202.             function(e){ var t = e.target; var n = t.childNodes[t.selectedIndex]; showDomainPrefDialog(n.label, n.value); return true; },
  203.             true);
  204.  
  205. }
  206.  
  207. function showDomainPrefDialog(domain, jsonStr) {
  208.     var jsonObj = JSON.parse(jsonStr);
  209.     document.getElementById("textoOptDomain").value = domain;
  210.     document.getElementById("textoOptDelete").disabled = false;
  211.     document.getElementById("textoOptSave").disabled = false;
  212.     document.getElementById("textoOptEditor").disabled = false;
  213.     document.getElementById("textoOptAuto").disabled = false;
  214.     document.getElementById("textoOptEnabled").disabled = false;
  215.     document.getElementById("textoOptArgs").disabled = false;
  216.     document.getElementById("texto.domain.editorbrowse").disabled = false;
  217.  
  218.     var opts = {textoOptEditor:'value', textoOptArgs:'value', textoOptAuto:'value', textoOptEnabled:'checked'};
  219.     for(var i in opts){
  220.         var node = document.getElementById(i);
  221.         if(typeof(jsonObj[i]) != "undefined"){
  222.             node[opts[i]] = jsonObj[i];
  223.         } else {
  224.             node[opts[i]] = '';
  225.         }
  226.     }
  227.  
  228. }
  229.  
  230. function resetDomainPrefDialog(){
  231.     showDomainPrefDialog("", JSON.stringify({textoOptEditor:'', textoOptArgs:'', textoOptAuto:'', textoOptEnabled:false}));
  232.     document.getElementById("textoOptDelete").disabled = true;
  233.     document.getElementById("textoOptSave").disabled = true;
  234.     document.getElementById("textoOptEditor").disabled = true;
  235.     document.getElementById("textoOptAuto").disabled = true;
  236.     document.getElementById("textoOptEnabled").disabled = true;
  237.     document.getElementById("textoOptArgs").disabled = true;
  238.     document.getElementById("texto.domain.editorbrowse").disabled = true;
  239. }
  240.  
  241.  
  242. function updateMozexPref(prefBox) {
  243.     if(prefBox.id.indexOf('texto.') != 0){ return; }
  244.     var prefName = prefBox.id.substring('texto.'.length);
  245.     texto_prefs.setCharPref(prefName, prefBox.value);
  246. }
  247.  
  248. function changeMozexPrefs(el) {
  249.     texto_prefs.setCharPref("command.textarea", document.getElementById("prefMozexTextareaEditor").value);
  250. }
  251.  
  252.  
  253. /* 
  254.  * Domain Database handling functions
  255.  */
  256.  
  257. function initDomainDb(){
  258.  
  259.     // Domain Database Querying:
  260.     var file = Components.classes["@mozilla.org/file/directory_service;1"]
  261.                          .getService(Components.interfaces.nsIProperties)
  262.                          .get("ProfD", Components.interfaces.nsIFile);
  263.     file.append("domain_prefs.sqlite");
  264.     var storageService = Components.classes["@mozilla.org/storage/service;1"]
  265.                             .getService(Components.interfaces.mozIStorageService);
  266.     dbConn = storageService.openDatabase(file); // Will also create the file if it does not exist
  267.     if(dbConn){
  268.         dbConn.executeSimpleSQL("CREATE TABLE IF NOT EXISTS domain_options (domain TEXT, extension TEXT, create_date TEXT DEFAULT CURRENT_TIMESTAMP, modify_date TEXT DEFAULT CURRENT_TIMESTAMP, jsonblob BLOB, PRIMARY KEY(domain ASC, extension ASC))");
  269.     }
  270. }
  271.  
  272. function getExtensionPrefList(extension, callback){
  273.     var mycallback = function(jsonObj){ callback(jsonObj[extension]); }
  274.     var rowcount = 0;
  275.     var jsonList = Array();
  276.  
  277.     if(dbConn == null) { initDomainDb(); }
  278.     var stmt = dbConn.createStatement("SELECT * FROM domain_options WHERE extension = :extension ORDER BY domain ASC");
  279.     stmt.params.extension = extension;
  280.     stmt.executeAsync({
  281.         handleResult: function(resultSet){
  282.             for(var row = resultSet.getNextRow(); row; row = resultSet.getNextRow()) {
  283.                 var jsonStr = row.getResultByName("jsonblob");
  284.                 var domain = row.getResultByName("domain");
  285.                 jsonList[domain] = jsonStr;
  286.             }
  287.             GLOBAL_QUERY_STATUS_THINGY = 1;
  288.             callback(jsonList);
  289.         },
  290.         handleError: function(err){ alert("Error: " + err.message); },
  291.         handleCompletion: function(reason){
  292.             if(reason != Components.interfaces.mozIStorageStatementCallback.REASON_FINISHED){ print("Query cancelled or aborted"); }
  293.             else { if(GLOBAL_QUERY_STATUS_THINGY == 0){ callback(Array()); } else GLOBAL_QUERY_STATUS_THINGY = 0; }
  294.             },
  295.     });
  296. }
  297.  
  298. function getDomainPrefStr(domain, extension, callback){
  299.     if(dbConn == null){ initDomainDb(); }
  300.     var jsonStr = "{}";
  301.     var stmt = dbConn.createStatement("SELECT * FROM domain_options WHERE extension = :extension AND :domain LIKE domain_options.domain||'%' ORDER BY domain_options.domain DESC");
  302.     stmt.params.extension = extension;
  303.     stmt.params.domain = urlReverse(domain);
  304.     stmt.executeAsync({
  305.         handleResult: function(resultSet){
  306.             var row = resultSet.getNextRow();
  307.             jsonStr = row.getResultByName("jsonblob");
  308.             GLOBAL_QUERY_STATUS_THINGY = 1;
  309.             callback(jsonStr);
  310.         },
  311.         handleError: function(err){ alert("Error: " + err.message); },
  312.         handleCompletion: function(reason){
  313.             if(reason != Components.interfaces.mozIStorageStatementCallback.REASON_FINISHED){ alert("Query cancelled or aborted"); }
  314.             else { if(GLOBAL_QUERY_STATUS_THINGY == 0){ callback(jsonStr); } else GLOBAL_QUERY_STATUS_THINGY = 0; }
  315.             },
  316.     });
  317. }
  318.  
  319. function addExtensionPrefObj(domain, extension, obj, callback){
  320.     var mycallback = function(jsonObj){
  321.         addDomainPrefStr(domain, extension, JSON.stringify(obj), callback);
  322.     }
  323.     getDomainPrefStr(domain, extension, mycallback);
  324. }
  325.  
  326. function addDomainPrefStr(domain, extension, jsonStr, callback){
  327.     if(dbConn == null){ initDomainDb(); }
  328.     var rdomain = urlReverse(domain);
  329.     var stmt = dbConn.createStatement("REPLACE INTO domain_options (domain, extension, jsonblob) VALUES(:domain, :extension, :jsonblob)");
  330.     stmt.params.domain = rdomain;
  331.     stmt.params.jsonblob = jsonStr;
  332.     stmt.params.extension = extension;
  333.     stmt.executeAsync({
  334.         handleResult: function(resultSet){},
  335.         handleError: function(err){ alert("Error saving: " + err.message); },
  336.         handleCompletion: function(reason){ callback(); },
  337.     });
  338. }
  339.  
  340. function delDomainPref(domain, extension, callback){
  341.     if(dbConn == null){ initDomainDb(); }
  342.     var rdomain = urlReverse(domain);
  343.     var stmt = dbConn.createStatement("DELETE FROM domain_options WHERE domain = :domain AND extension = :extension");
  344.     stmt.params.domain = rdomain;
  345.     stmt.params.extension = extension;
  346.     stmt.executeAsync({
  347.         handleError: function(err){ alert("Error saving: " + err.message); },
  348.         handleCompletion: function(reason){ callback(); },
  349.     });
  350.  
  351. }
  352.  
  353. /*
  354.  * URL handling functions
  355.  */
  356.  
  357. function urlReverse(url) {
  358.     var urlObj = parseUrl(url);
  359.     var rparts = urlObj.host.split("").reverse();
  360.     var rdomain = rparts.join("");
  361.     return rdomain + urlObj.path;
  362. }
  363.  
  364. function strcmp(a, b){ return ( ( a == b ) ? 0 : ( ( a > b ) ? 1 : -1 ) ); }
  365.  
  366. function parseUrl(url){
  367.     var urlObj = {};
  368.     urlObj.orig = url;
  369.     var slash = url.indexOf('/');
  370.     if(slash == -1){
  371.         urlObj.host = url;
  372.         urlObj.path = "";
  373.     } else {
  374.         urlObj.host = url.substr(0, slash);
  375.         urlObj.path = url.substr(slash);
  376.     }
  377.     urlObj.hostparts = urlObj.host.split(".");
  378.     if(urlObj.hostparts.length == 1){
  379.         urlObj.domain = urlObj.host;
  380.     } else {
  381.         var l = urlObj.hostparts.length;
  382.         urlObj.domain = urlObj.hostparts[l - 2] + '.' + urlObj.hostparts[l - 1];
  383.     }
  384.     return urlObj;
  385. }
  386.  
  387.  
  388. function isSubdomain(domain, subdomain){
  389.     if(domain.length >= subdomain.length){ return false; }
  390.     var idx = subdomain.indexOf(domain);
  391.     if(idx == 0 && subdomain.substr(domain.length, 1) == '.'){
  392.         return true;
  393.     }
  394.     return false;
  395. }
  396.  
  397. function domainCmp(a, b){
  398.     if(a == b) return 0;
  399.  
  400.     var aUrl = parseUrl(a);
  401.     var bUrl = parseUrl(b);
  402.  
  403.     // if the hosts are the same, sort by just path:
  404.     if(aUrl.host == bUrl.host){ return strcmp(aUrl.path, bUrl.path); }
  405.  
  406.     var maxlen = (aUrl.hostparts.length > bUrl.hostparts.length) ? aUrl.hostparts.length : bUrl.hostparts.length;
  407.     // if the domains are different, sort by them
  408.     if(aUrl.domain != bUrl.domain){ return strcmp(aUrl.domain, bUrl.domain); }
  409.  
  410.     // then descend until we find a difference
  411.     for(var i = maxlen - 2; i >= 0; i--){
  412.         if(typeof(aUrl.hostparts[i]) == "undefined"){
  413.             if(typeof(bUrl.hostparts[i]) == "undefined"){ return 0; }
  414.             else { return -1; }
  415.         } else {
  416.             if(typeof(bUrl.hostparts[i]) == "undefined"){ return 1; }
  417.             else if(aUrl.hostparts[i] != bUrl.hostparts[i]){
  418.                 return strcmp(aUrl.hostparts[i], bUrl.hostparts[i]);
  419.             }
  420.             // itentionally no 'else'; loop if equal
  421.         }
  422.     }
  423.  
  424.     // we already checked for a.host == b.host, so we never get here, right?
  425.     // return 0 to "safely" do nothing
  426.     return 0;
  427. }
  428.  
  429.  
  430.